package com.wmyg.antifake.dao;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.wmyg.antifake.bean.*;
import com.wmyg.antifake.sdk.FabricException;
import com.wmyg.antifake.sdk.ManageBuilder;
import com.wmyg.antifake.sdk.SmartManager;
import com.wmyg.antifake.utils.Dozen;
import com.wmyg.antifake.utils.GZipUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@Slf4j
@Repository
public class FabricDao {

    @Autowired
    SmartManager smartManager;

    public void enterItems(UnitInfo items, String batchKey, Dozen dozen) throws Throwable {
        log.info("The batchKey is {}", batchKey);
        log.info("The params is {}, {}, {} ,{}", items, dozen.getLevel(), dozen.getDozenId(), dozen.getCount());
        log.info("The dozen of qrs size is {}", dozen.getQrs().size());
        String qRsJson = JSON.toJSONString(dozen.getQrs());
        log.info("-------------------39----------------");
//        log.info("The qrJson is {}, length is {}", qRsJson, qRsJson.length());
        String gizpJson = GZipUtils.compress(qRsJson);
        log.info("-------------------42----------------");
        log.info("The gizped json is , length is {}", gizpJson.length());
        String md5Json = GZipUtils.md5(gizpJson);
        log.info("The md5 value is {}", md5Json);
        log.info("-------------------45----------------");
        String[] args = new String[]{batchKey, items.getProductTime(), items.getItemNo(), items.getEnterBatch(), items.getProducer(), items.getEnvironment(), items.getMaterialBatch(), items.getEnterTime(), items.getNumOfSonPacks().toString(), dozen.getLevel(), gizpJson, md5Json, Integer.toString(gizpJson.length())};
        log.info("-------------------47----------------");
//        SmartManager smartManager = ManageBuilder.buildManagerToUse("south", "User1", "antifake", "developchannel");
//        Map<String, String> map = smartManager.invoke("enterItems", args);
        Map<String, String> map = smartManager.invoke("enterItemsCompressed", args);
        log.info("-------------------51----------------");
        if ("success".equals(map.get("code"))) {
            log.info("Success add items");
        }
    }

//    public UnitInfo queryFirstTime(String batchKey, String qR, QueryInfo queryInfo) throws Throwable {
//        String[] args = new String[]{batchKey, qR, queryInfo.getAddress(), queryInfo.getQueryTime()};
//        SmartManager smartManager = ManageBuilder.buildManagerToUse("south", "User1", "antifake", "developchannel");
//        Map<String, String> map = smartManager.invoke("queryByQRFirstTime", args);
//        if (map.get("code").equals("success")) {
//            log.info("Query Success for QR: " + qR);
//        }
//        return JSON.parseObject(map.get("data"), UnitInfo.class);
//    }

    public QRInfo query(String qR, QueryInfo queryInfo) throws Throwable {
        String[] args = new String[]{qR, queryInfo.getAddressInfo().getAddressDetail(), queryInfo.getQueryTime(),
                queryInfo.getUserAgent(), Float.toString(queryInfo.getAddressInfo().getCoordinates()[0]),
        Float.toString(queryInfo.getAddressInfo().getCoordinates()[1]), queryInfo.getAddressInfo().getIpAddress(),
        queryInfo.getAppUserId()};
        log.info("Track by args {}--------------------------------------------", Arrays.toString(args));
//        SmartManager smartManager = ManageBuilder.buildManagerToUse("south", "User1", "antifake", "developchannel");
//        Map<String, String> map = smartManager.invoke("queryQRInfo", args);
        Map<String, String> map = smartManager.invoke("queryQRInfo", args);//Compressed
        if ("success".equals(map.get("code"))) {
            log.info("Query Success for QR: " + qR);
        }
        QRInfo qrInfo = JSON.parseObject(map.get("data"), QRInfo.class);
        int size = 0;
        if (null != qrInfo.getQueryHistory()) {
            size = qrInfo.getQueryHistory().size();
        }
        log.info("This qr {} is queried for {} times, this result is from chaincode------------------------------------------",qR , size);
        return qrInfo;
    }

    public void setHash(String key, Object object) throws Throwable {
        String[] args = new String[]{key, getSHA256StrJava(object.toString())};
//        SmartManager smartManager = ManageBuilder.buildManagerToUse("south", "User1", "antifake", "developchannel");
        Map<String, String> map = smartManager.invoke("setHash", args);
        if ("success".equals(map.get("code"))) {
            log.info("Create Hash Success");
        }
    }

    public void checkHash(String key, Object object) throws Throwable {
        String[] args = new String[]{key, getSHA256StrJava(object.toString())};
//        SmartManager smartManager = ManageBuilder.buildManagerToUse("south", "User1", "antifake", "developchannel");
        Map<String, String> map = smartManager.query("checkHash", args);
        if ("success".equals(map.get("code"))) {
            log.info("Check Hash Success");
        }
    }

    public static String getSHA256StrJava(String str){
        MessageDigest messageDigest;
        String encodeStr = "";
        try {
            messageDigest = MessageDigest.getInstance("SHA-256");
            messageDigest.update(str.getBytes("UTF-8"));
            encodeStr = byte2Hex(messageDigest.digest());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return encodeStr;
    }

    private static String byte2Hex(byte[] bytes){
        StringBuffer stringBuffer = new StringBuffer();
        String temp = null;
        for (int i=0;i<bytes.length;i++){
            temp = Integer.toHexString(bytes[i] & 0xFF);
            if (temp.length()==1){
                //1得到一位的进行补0操作
                stringBuffer.append("0");
            }
            stringBuffer.append(temp);
        }
        return stringBuffer.toString();
    }

    public static String zip(String data) {
        byte[] b = null;
        ByteArrayOutputStream bos = null;
        ZipOutputStream zip = null;
        byte[] dataAsBytes = data.getBytes();
        try {
            bos = new ByteArrayOutputStream();
            zip = new ZipOutputStream(bos);
            ZipEntry zipEntry = new ZipEntry("zip");
            zipEntry.setSize(dataAsBytes.length);
            zip.putNextEntry(zipEntry);
            zip.write(dataAsBytes);
            zip.closeEntry();
            zip.close();
            b = bos.toByteArray();
            bos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new String(b);
    }

    public List<DataPre> getPreData(String batchkey) throws Throwable {
        String[] args = new String[]{batchkey};
//        SmartManager smartManager = ManageBuilder.buildManagerToUse("south", "User1", "antifake", "developchannel");
        Map<String, String> map = smartManager.query("dataPrepare", args);
        log.info("Success get data:" + map.get("data"));
        return JSONArray.parseArray(map.get("data"), DataPre.class);
    }

    public void uploadBill(Bill bill) throws Throwable {
        String boxes = JSON.toJSONString(bill.getBoxes());
        String[] args = new String[]{bill.getCaseId(), boxes};
//        SmartManager smartManager = ManageBuilder.buildManagerToUse("south", "User1", "antifake", "developchannel");
        Map<String, String> map = smartManager.invoke("enterCaseBill", args);
        if ("success".equals(map.get("code"))) {
            log.info("Upload case " + bill.getCaseId() + " of " + bill.getBillId() + " success");
        }
    }

}
